package net.javacrumbs.shedlock.support;

import net.javacrumbs.shedlock.core.LockConfiguration;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import sun.misc.Unsafe;
import java.lang.reflect.Field;

/**
 * 自定义数据库锁
 */
public class CustomizedTemplateLockProvider extends JdbcTemplateLockProvider {
    private static final Logger logger = LoggerFactory.getLogger(CustomizedTemplateLockProvider.class);

    private final JdbcTemplate jdbcTemplate;
    private final JdbcTemplateLockProvider.Configuration configuration;
    private LockRecordRegistry parentLockRecordRegistry;

    public CustomizedTemplateLockProvider(JdbcTemplateLockProvider.Configuration configuration) {
        super(configuration);
        this.configuration = configuration;
        this.jdbcTemplate = configuration.getJdbcTemplate();
        this.initializeLockRecordRegistry();
    }

    /**
     * 初始化 LockRecordRegistry
     */
    private void initializeLockRecordRegistry() {
        try {
            Field lockRecordRegistryField = StorageBasedLockProvider.class.getDeclaredField("lockRecordRegistry");
            lockRecordRegistryField.setAccessible(true);
            this.parentLockRecordRegistry = (LockRecordRegistry) lockRecordRegistryField.get(this);
        } catch (ReflectiveOperationException e) {
            logger.warn("无法初始化 lockRecordRegistry, 锁记录管理可能无法启用: {}", e.getMessage(), e);
        }
    }

    @Override
    protected boolean doLock(LockConfiguration lockConfiguration) {
        if (parentLockRecordRegistry == null) {
            // 如果未成功获取 lockRecordRegistry，直接使用父类逻辑
            return super.doLock(lockConfiguration);
        }

        String lockName = lockConfiguration.getName();
        if (!parentLockRecordRegistry.lockRecordRecentlyCreated(lockName)) {
            try {
                String tableName = configuration.getTableName();
                String nameColumn = configuration.getColumnNames().getName();
                String querySql = "SELECT COUNT(1) FROM " + tableName + " WHERE " + nameColumn + " = ?";
                Long count = jdbcTemplate.queryForObject(querySql, Long.class, lockName);

                if (count != null && count > 0) {
                    parentLockRecordRegistry.addLockRecord(lockName);
                }
            } catch (Exception e) {
                logger.warn("在查询锁记录时出现异常: lockConfiguration={}, 异常信息={}", lockConfiguration, e.getMessage(), e);
            }
        }

        // 调用父类方法进行实际加锁
        return super.doLock(lockConfiguration);
    }

    private String name() {
        return this.configuration.getColumnNames().getName();
    }

    private String tableName() {
        return this.configuration.getTableName();
    }
}
